using System;
using System.Net;
using System.Runtime.CompilerServices;
using System.Text;
using Opc.Ua;
using Opc.Ua.Configuration;

namespace HslCommunicationEx.OpcUa.Server
{
	public class PeanutOpcUaManager<T> where T : PeanutOpcUaNodeManager
	{
		public int MinRequestTdCount { get; set; } = 5;


		public int MaxRequestTdCount { get; set; } = 100;


		public int MaxQueuedRequestCount { get; set; } = 200;


		public int OperationTimeout { get; set; } = 15000;


		public int DefaultSessionTimeout { get; set; } = 60000;


		public PeanutOpcUaServer<T> CusOpcServer { get; set; }

		public PeanutOpcUaManager()
		{
			this.CusOpcServer = new PeanutOpcUaServer<T>
			{
				NameSpace = "SinumerikVarProvider"
			};
		}

		public Tuple<bool, string> CreateServerInstance(string serverIp, int port, UserTokenType userTokenType = UserTokenType.Anonymous, string appName = "OpcUaServer")
		{
			ApplicationConfiguration applicationConfiguration = new ApplicationConfiguration();
			applicationConfiguration.ApplicationName = appName;
			applicationConfiguration.ApplicationUri = Utils.Format("urn:" + Dns.GetHostName() + ":" + appName);
			applicationConfiguration.ApplicationType = ApplicationType.Server;
			ServerConfiguration serverConfiguration = new ServerConfiguration();
			StringCollection baseAddresses = serverConfiguration.BaseAddresses;
			DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(12, 3);
			defaultInterpolatedStringHandler.AppendLiteral("opc.tcp://");
			defaultInterpolatedStringHandler.AppendFormatted(serverIp);
			defaultInterpolatedStringHandler.AppendLiteral(":");
			defaultInterpolatedStringHandler.AppendFormatted(port);
			defaultInterpolatedStringHandler.AppendLiteral("/");
			defaultInterpolatedStringHandler.AppendFormatted(appName);
			baseAddresses.Add(defaultInterpolatedStringHandler.ToStringAndClear());
			serverConfiguration.MinRequestThreadCount = this.MinRequestTdCount;
			serverConfiguration.MaxRequestThreadCount = this.MaxRequestTdCount;
			serverConfiguration.MaxQueuedRequestCount = this.MaxQueuedRequestCount;
			serverConfiguration.MaxRegistrationInterval = 0;
			applicationConfiguration.ServerConfiguration = serverConfiguration;
			applicationConfiguration.SecurityConfiguration = new SecurityConfiguration
			{
				ApplicationCertificate = new CertificateIdentifier
				{
					StoreType = "Directory",
					StorePath = "%CommonApplicationData%\\OPC Foundation\\CertificateStores\\MachineDefault",
					SubjectName = Utils.Format("CN={0}, DC={1}", appName, Dns.GetHostName())
				},
				TrustedIssuerCertificates = new CertificateTrustList
				{
					StoreType = "Directory",
					StorePath = "%CommonApplicationData%\\OPC Foundation\\CertificateStores\\UA Certificate Authorities"
				},
				TrustedPeerCertificates = new CertificateTrustList
				{
					StoreType = "Directory",
					StorePath = "%CommonApplicationData%\\OPC Foundation\\CertificateStores\\UA Applications"
				},
				RejectedCertificateStore = new CertificateTrustList
				{
					StoreType = "Directory",
					StorePath = "%CommonApplicationData%\\OPC Foundation\\CertificateStores\\RejectedCertificates"
				},
				AutoAcceptUntrustedCertificates = true,
				AddAppCertToTrustedStore = true
			};
			applicationConfiguration.TransportConfigurations = new TransportConfigurationCollection();
			applicationConfiguration.TransportQuotas = new TransportQuotas
			{
				OperationTimeout = this.OperationTimeout
			};
			applicationConfiguration.ClientConfiguration = new ClientConfiguration
			{
				DefaultSessionTimeout = this.DefaultSessionTimeout
			};
			applicationConfiguration.TraceConfiguration = new TraceConfiguration();
			ApplicationConfiguration applicationConfiguration2 = applicationConfiguration;
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				StringBuilder stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder3 = stringBuilder2;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(4, 3, stringBuilder2);
				handler.AppendLiteral("Uri:");
				handler.AppendFormatted(Environment.NewLine);
				handler.AppendFormatted(applicationConfiguration2.ApplicationUri);
				handler.AppendFormatted(Environment.NewLine);
				stringBuilder3.Append(ref handler);
				foreach (string baseAddress in applicationConfiguration2.ServerConfiguration.BaseAddresses)
				{
					stringBuilder2 = stringBuilder;
					StringBuilder stringBuilder4 = stringBuilder2;
					handler = new StringBuilder.AppendInterpolatedStringHandler(12, 3, stringBuilder2);
					handler.AppendLiteral("BaseAddress:");
					handler.AppendFormatted(Environment.NewLine);
					handler.AppendFormatted(baseAddress);
					handler.AppendFormatted(Environment.NewLine);
					stringBuilder4.Append(ref handler);
				}
				applicationConfiguration2.Validate(ApplicationType.Server).GetAwaiter().GetResult();
				if (applicationConfiguration2.SecurityConfiguration.AutoAcceptUntrustedCertificates)
				{
					applicationConfiguration2.CertificateValidator.CertificateValidation += delegate(CertificateValidator s, CertificateValidationEventArgs e)
					{
						e.Accept = true;
					};
				}
				if (applicationConfiguration2.ServerConfiguration.UserTokenPolicies.Count > 0)
				{
					applicationConfiguration2.ServerConfiguration.UserTokenPolicies[0].TokenType = userTokenType;
				}
				ApplicationInstance applicationInstance = new ApplicationInstance
				{
					ApplicationName = appName,
					ApplicationType = ApplicationType.Server,
					ApplicationConfiguration = applicationConfiguration2
				};
				if (!applicationInstance.CheckApplicationInstanceCertificate(silent: false, 0).Result)
				{
					return new Tuple<bool, string>(item1: false, "Certificate validation failed!");
				}
				applicationInstance.Start(this.CusOpcServer).Wait();
				return new Tuple<bool, string>(item1: true, stringBuilder.ToString());
			}
			catch (Exception innerException)
			{
				throw new Exception(appName + " Start failed!", innerException);
			}
		}
	}
}
